package es.xpt.ysf.commons.jcr;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import es.xpt.ysf.dao.DAOUtils;
import es.xpt.ysf.jaas.YSFPrincipal;
import es.xpt.ysf.logging.LogManager;

public class JcrManager {
	
	private YSFPrincipal principal;
	
	public JcrManager (YSFPrincipal principal ) {
		this.principal = principal;
	}
	
	private Session init () {
		try {
			InitialContext ctx = new InitialContext();
			Repository repo = (Repository) ctx.lookup(DAOUtils.getJcrDsJndiName(principal));
			return repo.login(new SimpleCredentials("username", "password".toCharArray()));
		} catch (NamingException e) {
			LogManager.getLog(getClass()).error(e.getMessage(), e);
			return null;
		} catch (RepositoryException e) {
			LogManager.getLog(getClass()).error(e.getMessage(), e);
			return null;
		}
	}
	
	private InputStream getFirstImageStream(Session s, String path, String namePattern) {

		try {
			Node root = s.getRootNode();
            Node images = root.getNode("default/" + path + "/images");
            NodeIterator ni = images.getNodes(namePattern);
            if (ni.hasNext()) {
            	Node image = ni.nextNode().getNode("jcr:content");
            	if ( image!=null )	            	
                	return image.getProperty("jcr:data").getStream();	
            }
		} catch ( javax.jcr.ItemNotFoundException e ) {
			LogManager.getLog(getClass()).debug(e.getMessage(), e);
		} catch ( javax.jcr.PathNotFoundException e ) {
			LogManager.getLog(getClass()).debug(e.getMessage(), e);
		} catch (RepositoryException e) {
			LogManager.getLog(getClass()).debug(e.getMessage(), e);
		}
		return null;
		
	}
	
	public List<Node> getAllDocsFiles(String path, String namePattern, String defaultPattern){
		Session s = null;
		try {
			s = init();
			if ( s == null ) 
				return null;
			
			List<Node> result = getAllDocsFiles(s, path, namePattern);
			if (result == null) 
				result = getAllDocsFiles(s, path, defaultPattern);
			 
			return result;
			
		} finally {
			if (s != null)
				s.logout();
		}
	}
	
	private List<Node> getAllDocsFiles(Session s, String path,
			String namePattern) {
		try {
			Node root = s.getRootNode();
            Node nodes = root.getNode("default/" + path + "/otherDocs");
            NodeIterator ni = nodes.getNodes(namePattern);
            List<Node> result = new ArrayList<Node>();
            while (ni.hasNext()) {
            	Node node = ni.nextNode();
            	if ( node!=null ){
            		result.add(node);
            	}
            }
            return result;
		} catch ( javax.jcr.ItemNotFoundException e ) {
			LogManager.getLog(getClass()).debug(e.getMessage(), e);
		} catch ( javax.jcr.PathNotFoundException e ) {
			LogManager.getLog(getClass()).debug(e.getMessage(), e);
		} catch (RepositoryException e) {
			LogManager.getLog(getClass()).debug(e.getMessage(), e);
		}
		return null;
	}

	public InputStream getFirstImageStream(String path, String namePattern, String defaultPattern)  {
		Session s = null;
		try {
			s = init();
			if ( s == null ) 
				return null;
			
			InputStream result = getFirstImageStream(s, path, namePattern);
			if (result == null) 
				result = getFirstImageStream(s, path, defaultPattern);
			 
			return result;
			
		} finally {
			if (s != null)
				s.logout();
		}
		
	}


	public String addFile ( String path, String id, String folder, String contentName,
			InputStream inputStream, String mimeType ) throws RepositoryException {
		if ( path == null || path.isEmpty() ) {
			throw new NullPointerException("path");
		}
		if ( id == null || id.isEmpty() ) {
			throw new NullPointerException("entityId");
		}
		
		Session s = null;
		try {
            s = init();
            if ( s == null )
            	return null;
            Node root = s.getRootNode();
            Node type = root.getNode("default/" + path); 
            
            Node folderNode;
            try {
            	folderNode = type.getNode( id + "/" + folder); // type.getNode("prueba/images");
            } catch (PathNotFoundException e) {
            	Node entity;
            	try {
            		entity = type.getNode(id);
            	} catch (PathNotFoundException e2) {
            		entity = type.addNode(id);
            	}
            	folderNode = entity.addNode(folder, "nt:folder");
            }
//	            String fileName = file.getName();
//	            fileName = fileName.substring(fileName.lastIndexOf('\\')+1);
//	            fileName = fileName.substring(fileName.lastIndexOf('/')+1);
            String fileName = contentName;
            
            Node fileNode = folderNode.addNode(fileName, "nt:file");
            Node resNode = fileNode.addNode("jcr:content", "nt:resource");
    		resNode.setProperty("jcr:mimeType", mimeType);
    		resNode.setProperty("jcr:encoding", "");
    		resNode.setProperty("jcr:data", inputStream);
    		Calendar lastModified = Calendar.getInstance();
    		resNode.setProperty("jcr:lastModified", lastModified);

    		s.save();
    		return resNode.getUUID();
			
		} finally {
			if ( s!=null ) s.logout();
		}
	}
	
	public List<String> getPublicImagesPaths(String path, String entityId) {
		Session s = null;
		try {
			s = init();
			if ( s==null )
				return null;
			
            Node root = s.getRootNode();
            try {
	            Node images = root.getNode("default/" + path + "/" + entityId + "/images"); //product/LODGING/prueba/images
	            NodeIterator ni = images.getNodes();
	            
	            List<JcrNodeInfo> nodesInfo = new ArrayList<JcrNodeInfo>();
	            
	            while (ni.hasNext()) {
	            	Node n = ni.nextNode();
	            	JcrNodeInfo jcrNodeInfo = new JcrNodeInfo();
	            	Node contentNode = n.getNode("jcr:content");
	            	jcrNodeInfo.setId(contentNode.getUUID());
	            	jcrNodeInfo.setName(n.getName());
	            	nodesInfo.add(jcrNodeInfo);
	            	
	            	if (contentNode.hasProperty("ysf:order")){
	            		 jcrNodeInfo.setOrder(
	            				Integer.parseInt(contentNode.getProperty("ysf:order").getValue().getString()));
	            	}else{
	            		 jcrNodeInfo.setOrder(Integer.MAX_VALUE);
	            	}
	            }
            
	            Collections.sort(nodesInfo);    
	            
	            //Preparo la lista de urls
	            List<String> imagesList = new ArrayList<String>(5);
	            
	            for (JcrNodeInfo jni : nodesInfo) {	            	
	            	imagesList.add(jni.getId());
	            }
	            return imagesList;
            } catch (PathNotFoundException e) {
            	return null;
            }
                        
		} catch (RepositoryException e) {
			LogManager.getLog(getClass()).error(e.getMessage(), e);
			return null;
		} finally {
			if ( s!=null ) s.logout();
		}
	}
}
